﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;
using BbsbWebService.Enums;
using BbsbWebService.Repositories;
using System.ComponentModel;
using System.ServiceModel;
using System.Xml.Linq;
using BbsbWebService.Classes.Plugins.Bbsb;
using BbsbWebService.Classes.Plugins.KeyMap;
using BbsbWebService.Classes.Controllers;

namespace BbsbWebService.Classes
{
    [DataContract]
    [ServiceKnownType("PluginItemTypes", typeof(AppSettings))]
    public abstract class ControllableItem : CommandItem
    {
        public ControllableItem()
        {
            // Ensure that Groups is not null on initial construction
            Groups = new List<Group>();
        }

        public List<Group> Groups { get; set; }

        [DataMember]
        public BaseItem[] BaseGroups
        {
            get
            {
                return Groups.ToBaseItemArray();
            }
            set
            {
                if (value != null)
                {
                    foreach (var bob in value)
                    {
                        if (RepositoryInstances.GroupRepository.HasItem(bob.Id))
                        {
                            Group group = RepositoryInstances.GroupRepository.GetItem(bob.Id);
                            if (Groups == null)
                            {
                                Groups = new List<Group>();
                            }
                            Groups.Add(group);
                        }
                    }
                }
            }
        }

        public abstract IController Controller { get; }

        public IEnumerable<Group> NotGroups
        {
            get
            {
                return RepositoryInstances.GroupRepository.Items.Where(o => !Groups.Any(p => p.Id == o.Id));
            }
        }

        protected override void Validate(ref ValidationState state)
        {
            base.Validate(ref state);
            if (Command.IsNullOrEmpty())
                state.AddError("Item must have a command.");
        }

        public virtual void SendPower(PowerOption option)
        {
            if (!IsAlwaysStateAware || (int)State != (int)option)
            {
                Controller.SendCommand(GetCommand(option));
            }
            State = (PowerState)((int)option);
        }

        protected abstract string GetCommand(PowerOption option);

        public virtual void AddItemDependantProperty(XElement element) { }

        public virtual IEnumerable<XElement> SaveAdditionalProperties() { return null; }

        public abstract Type ControllerType { get; }

        public string TypeName
        {
            get { return this.GetType().Name.Replace("Item", string.Empty); }
        }
    }
}
